Skip to content

Conversation

@9romise
Copy link
Contributor

@9romise 9romise commented Aug 22, 2025

Hi 👋, Vue team!

I've been trying to contribute to eslint-plugin-vue and recently noticed there might be plans to rewrite it in TypeScript, though things seem to have stalled. I’d like to help move this effort forward.

This PR introduces tsdown, a tool that can gradually transform mixed JavaScript/TypeScript codebases into pure JavaScript output. This allows us to incrementally migrate the entire project to TypeScript. I’ve already successfully rewritten several files — it works well.

Going forward, I can split the changes into multiple PRs to make review easier.

If there’s anything you’d like me to adjust in this PR, or if you have any feedback, I’d really appreciate your thoughts! 💚

Related: #2777

@changeset-bot
Copy link

changeset-bot bot commented Aug 22, 2025

⚠️ No Changeset found

Latest commit: 7e482cb

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@9romise 9romise changed the title feat: introduce tsdown, support js & ts feat: introduce tsdown, support mixed js & ts in codebase Aug 22, 2025
@9romise 9romise marked this pull request as draft August 22, 2025 02:24
@9romise 9romise marked this pull request as ready for review August 22, 2025 02:47
Copy link
Member

@FloEdelmann FloEdelmann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really nice, thank you!

@9romise

This comment was marked as resolved.

@9romise

This comment was marked as resolved.

Copy link
Contributor

@2nofa11 2nofa11 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If pull request #2931 is merged and incorporated into this PR, it may resolve some of the CI failures!!!

I believe this PR is an excellent fix 😍

@9romise

This comment was marked as resolved.

@9romise 9romise marked this pull request as ready for review November 22, 2025 16:42
@9romise

This comment was marked as outdated.

# Conflicts:
#	lib/plugin.js
#	tests/lib/rules/block-order.ts
#	tools/update-lib-plugin.js
@9romise 9romise marked this pull request as draft December 5, 2025 03:35
@9romise 9romise marked this pull request as ready for review December 5, 2025 03:43
@9romise 9romise requested a review from FloEdelmann December 5, 2025 03:43
Copy link
Member

@FloEdelmann FloEdelmann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's go then 🚀 🙂

Copy link
Member

@ota-meshi ota-meshi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Thank you so much!

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces tsdown as a build tool to enable gradual migration from JavaScript to TypeScript in the eslint-plugin-vue codebase. It converts several core files to TypeScript (lib/index.ts, lib/meta.ts, lib/processor.ts) while maintaining compatibility with the existing JavaScript files.

Key changes:

  • Adds tsdown build configuration and updates CI workflow with a dedicated build job
  • Converts core plugin files from CommonJS to TypeScript with ESM syntax
  • Changes package entry point from lib/index.js to dist/index.js (built output)

Reviewed changes

Copilot reviewed 12 out of 14 changed files in this pull request and generated 12 comments.

Show a summary per file
File Description
tsdown.config.ts Configures tsdown build tool with entry point, output format (CJS), and file copy settings
tsconfig.json Updates TypeScript compiler options for modern module resolution (bundler) and ESNext target
package.json Updates main/types entry points to dist directory and adds build script with tsdown
.gitignore Adds dist directory to ignored files
.github/workflows/CI.yml Adds build job and artifact caching for all test jobs
lib/index.ts Converts main entry point from CommonJS to TypeScript with ESM imports
lib/meta.ts Converts meta module to TypeScript using JSON import assertion
lib/processor.ts Converts processor from CommonJS/JSDoc to TypeScript with proper type annotations
lib/plugin.js Updates requires to reference TypeScript files with .default exports
tools/update-lib-plugin.js Updates generated code to require TypeScript files
tools/generate-typegen.mjs Updates import to reference TypeScript source file
docs/.vitepress/theme/components/eslint-code-block.vue Updates import path to reference lib source directory
Comments suppressed due to low confidence (1)

lib/processor.ts:160

  • The Position type is used in the function signature but is not imported or defined anywhere in this file. This will cause a TypeScript compilation error. The Position type should be imported from ESLint's types (e.g., import type { Linter } from 'eslint' and then use Linter.Position) or defined as an interface in this file.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

const plugin = {
meta: require('./meta'),
meta: require('./meta.ts').default,
Copy link

Copilot AI Dec 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using require('./meta.ts').default to import a TypeScript file from a CommonJS module is problematic. After tsdown transpiles the code, the file should be ./meta.js in the dist directory, not ./meta.ts. This will cause a runtime error because the .ts file won't exist in the built output. The require path should reference the transpiled .js file.

Copilot uses AI. Check for mistakes.
// Load linter.
const [plugin, { Linter }, vueEslintParser, globals] = await Promise.all([
import('../../../..'),
import('../../../../lib/index'),
Copy link

Copilot AI Dec 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The import path '../../../../lib/index' attempts to import from the source directory, but with the package.json change, the built output is now in the dist directory. This import should be updated to '../../../../dist/index' or '../../../../lib/index.js' (if the intent is to use the transpiled output), or ensure that Vite/VitePress is configured to handle TypeScript imports from lib/ directory.

Suggested change
import('../../../../lib/index'),
import('../../../../dist/index'),

Copilot uses AI. Check for mistakes.
Comment on lines +67 to +70
- name: Restore dist cache
uses: actions/download-artifact@v6
with:
name: dist
Copy link

Copilot AI Dec 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The download-artifact action is missing the path parameter to specify where the artifact should be extracted. By default, artifacts are downloaded to the current working directory, but it's unclear if that matches the expected dist location. The path parameter should be explicitly set to dist to ensure the artifact is extracted to the correct location.

Copilot uses AI. Check for mistakes.
Comment on lines +156 to +159
- name: Restore dist cache
uses: actions/download-artifact@v6
with:
name: dist
Copy link

Copilot AI Dec 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The download-artifact action is missing the path parameter to specify where the artifact should be extracted. By default, artifacts are downloaded to the current working directory, but it's unclear if that matches the expected dist location. The path parameter should be explicitly set to dist to ensure the artifact is extracted to the correct location.

Copilot uses AI. Check for mistakes.
Comment on lines +261 to +262
'.vue': require('./processor.ts').default,
vue: require('./processor.ts').default
Copy link

Copilot AI Dec 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using require('./processor.ts').default to import a TypeScript file from a CommonJS module is problematic. After tsdown transpiles the code, the file should be ./processor.js in the dist directory, not ./processor.ts. This will cause a runtime error because the .ts file won't exist in the built output. The require path should reference the transpiled .js file.

Suggested change
'.vue': require('./processor.ts').default,
vue: require('./processor.ts').default
'.vue': require('./processor.js').default,
vue: require('./processor.js').default

Copilot uses AI. Check for mistakes.
import fs from 'node:fs/promises'
import { pluginsToRulesDTS } from 'eslint-typegen/core'
import plugin from '../lib/index.js'
import plugin from '../lib/index.ts'
Copy link

Copilot AI Dec 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Importing a TypeScript file (../lib/index.ts) from an ESM module (.mjs) will fail at runtime because Node.js doesn't natively support TypeScript imports without a loader. Since the build script runs typegen before tsdown, this script executes before the TypeScript files are transpiled. Consider using a TypeScript loader, running this script with tsx/ts-node, or restructuring the build process so typegen runs after the build.

Suggested change
import plugin from '../lib/index.ts'
import plugin from '../lib/index.js'

Copilot uses AI. Check for mistakes.
Comment on lines +90 to +93
- name: Restore dist cache
uses: actions/download-artifact@v6
with:
name: dist
Copy link

Copilot AI Dec 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The download-artifact action is missing the path parameter to specify where the artifact should be extracted. By default, artifacts are downloaded to the current working directory, but it's unclear if that matches the expected dist location. The path parameter should be explicitly set to dist to ensure the artifact is extracted to the correct location.

Copilot uses AI. Check for mistakes.
Comment on lines +111 to +114
- name: Restore dist cache
uses: actions/download-artifact@v6
with:
name: dist
Copy link

Copilot AI Dec 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The download-artifact action is missing the path parameter to specify where the artifact should be extracted. By default, artifacts are downloaded to the current working directory, but it's unclear if that matches the expected dist location. The path parameter should be explicitly set to dist to ensure the artifact is extracted to the correct location.

Copilot uses AI. Check for mistakes.
Comment on lines +135 to +138
- name: Restore dist cache
uses: actions/download-artifact@v6
with:
name: dist
Copy link

Copilot AI Dec 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The download-artifact action is missing the path parameter to specify where the artifact should be extracted. By default, artifacts are downloaded to the current working directory, but it's unclear if that matches the expected dist location. The path parameter should be explicitly set to dist to ensure the artifact is extracted to the correct location.

Copilot uses AI. Check for mistakes.
node-version: lts/*

- name: Install Packages
run: npm install
Copy link

Copilot AI Dec 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The build job uses npm install without the --legacy-peer-deps flag, while the lint job uses npm install --legacy-peer-deps. This inconsistency could lead to different dependency resolution and potential build failures. The build job should use the same installation command as other jobs for consistency.

Suggested change
run: npm install
run: npm install --legacy-peer-deps

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants